package com.hfzy.ihk.web.freeswitchCall.support.freeswitch.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hfzy.ihk.common.constants.GlobalStatic;
import com.hfzy.ihk.common.eventSocket.constant.EventSubClassName;
import com.hfzy.ihk.common.eventSocket.enums.EventName;
import com.hfzy.ihk.common.util.date.DateUtils;
import com.hfzy.ihk.common.util.string.StringTools;
import com.hfzy.ihk.common.util.string.StringUtil;
import com.hfzy.ihk.web.freeswitchCall.biz.PushDataToEsBiz;
import com.hfzy.ihk.web.freeswitchCall.biz.PushDataToOracleBiz;
import com.hfzy.ihk.web.freeswitchCall.constant.*;
import com.hfzy.ihk.web.freeswitchCall.context.BeanUtils;
import com.hfzy.ihk.web.freeswitchCall.context.EventSocketInitBean;
import com.hfzy.ihk.web.freeswitchCall.support.freeswitch.base.AbstractCallStateHandler;
import com.hfzy.ihk.web.freeswitchCall.support.freeswitch.event.FreeswitchCallStateEvent;
import com.hfzy.ihk.web.freeswitchCall.support.websocket.WebSocketUtils;
import com.hfzy.ihk.facade.freeswitchCall.vo.CallHistory;
import com.hfzy.ihk.facade.freeswitchCall.vo.FreeswitchCallState;
import org.freeswitch.esl.client.transport.SendMsg;
import org.freeswitch.esl.client.transport.event.EslEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.hfzy.ihk.common.eventSocket.enums.EventName.CHANNEL_HANGUP_COMPLETE;

/**
 * @Auther: Administrator
 * @Date: 2018/11/13 11:06
 * @Description:
 */
@Scope("prototype")
@Component
public class FreeswitchCallStateHandler extends AbstractCallStateHandler<FreeswitchCallState, FreeswitchCallStateEvent> implements InitializingBean {

    Logger logger = LoggerFactory.getLogger(FreeswitchCallStateHandler.class);

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    WebSocketUtils webSocketUtils;

    @Resource
    TaskExecutor pushDataToEsTaskExecutor;

    @Resource
    TaskExecutor pushDataToOracleTaskExecutor;

    @Autowired
    PushDataToEsBiz pushDataToEsBiz;

    @Autowired
    PushDataToOracleBiz pushDataToOracleBiz;



    HashOperations hashOperations;

    //对外访问的url
    @Value("${freeswitch.web.recordFileUrl}")
    private String  recordFileUrl;


    @Value("${freeswitch.web.url}")
    private String serverUrl;

    @Autowired
    private EventSocketInitBean initBean;
    //freeswitch录音文件绝对路径
    @Value("${freeswitch.recordFileDiskPath}")
    private String recordFilePath;

    @Override
    public void afterPropertiesSet() throws Exception {

        hashOperations = redisTemplate.opsForHash();
    }


    @Override
    protected Map<String, CallHistory> getMemoryCache() {
        return null;
    }

    /**
     * 读取redis
     *
     * @param sessionId
     * @return
     */
    @Override
    protected Map<String, String> readRedis(String sessionId) {

        logger.debug("FreeswitchCallStateWorkHandler readRedis：" + sessionId);

        Map redisMap = hashOperations.entries(RedisKey.CALL_HISTORY_RPIX + sessionId);

        return redisMap;
    }

    @Override
    protected String handleReadRedisFailed(FreeswitchCallState Data) {
        return null;
    }

    /**
     * 将呼叫记录写入redis
     *
     * @param sessionId
     * @param map
     * @return
     */
    @Override
    protected String writeRedis(String sessionId, Map<String, String> map) {
        if (map.isEmpty()) {
            logger.debug("freeswitchCallStateHandler--->writeRedis --->map is Empty,");
            return Constants.FAIL;
        }

        if ("1".equals(map.get(RedisFields.CALL_HISTORY_CALL_TYPE)) || "2".equals(map.get(RedisFields.CALL_HISTORY_CALL_TYPE))) {
            redisTemplate.opsForHash().putAll(RedisKey.CALL_HISTORY_RPIX + sessionId, map);
            //超时时间三天
            redisTemplate.expire(RedisKey.CALL_HISTORY_RPIX + sessionId, RedisTimeOut.CACHE_THREE_DAY, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForHash().putAll(RedisKey.CALL_HISTORY_RPIX + sessionId, map);
        }
        return Constants.SUCCESS;
    }

    @Override
    protected String handleWriteRedisFailed(String sessionId, Map<String, String> map) {
        return null;
    }

    @Override
    protected boolean checkCanOrNotPushToBatchInsertQueue(Map<String, String> callHistoryMap, Map<String, String> redisMap, FreeswitchCallState data) {
        boolean ableInsert = false;
        if (data.getMsgType().equals(AliyunAkInfo.VOICEREPORT)) {
            ableInsert = true;
        }
        return ableInsert;
    }

    @Override
    protected void handlePushStateToClientFail() {
        logger.info("handlePushStateToClientFail ....FreeswitchCallState");
    }

    /**
     * 分析呼入状态
     *
     * @param callState
     * @param callHistoryMap
     * @return
     * @throws Exception
     */
    @Override
    protected Map<String, Map<String, String>> analyzeCallState(FreeswitchCallState callState, Map<String, String> callHistoryMap) throws Exception {


        logger.info("analyze callState:" + JSON.toJSONString(callState));
        logger.info("analyze callHistoryMap:" + JSON.toJSONString(callHistoryMap));
        //eventName
        EventName eventName = EventName.fromName(callState.getStatus_code());
//        String eventName = callState.getStatus_code();
        //取出event
        EslEvent event = callState.getEvent();
        //redisKey
        String redisKey = RedisKey.CALL_HISTORY_RPIX + callState.getSessionId();

        Map<String, Map<String, String>> resultMap = new HashMap<>(2);
        //返回给客户端的map
        Map<String, String> msgMap = new HashMap<>(2);
        Map<String, String> redisSaveMap = new HashMap<>();

        String nowDateStr = DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS);

        if (callState.getMsgType().equals(AliyunAkInfo.VOICECALLREPORT)) { //呼出中间状态
            switch (eventName) {
                case CHANNEL_CREATE:  //正在接通主叫 --当做提交成功 该状态不用推送给客户端

                    if (callState.getChannelName().contains(callState.getCaller())) {//判断是否为主叫

//                        try {
//                            //用于设定当前使用用户是否占线
//                            if (callHistoryMap.get(RedisFields.CREATE_USER_ID) != null) {
//                                redisTemplate.opsForHash().put(RedisKey.USER_BUSY, callHistoryMap.get(RedisFields.CREATE_USER_ID), Constants.TRUE);
//                            }
//                        } catch (Exception e) {
//                            logger.error("======>call state：{} ", callState.getStatus_code(), e);
//                        }

                    }
                    msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);

                    break;
                case CHANNEL_PROGRESS:  //用户响铃 该状态不用推送给客户端
                    if (callState.getChannelName().contains(callState.getCaller())) {

                        redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_RINGING_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                        redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_RINGING, Constants.TRUE);
                        redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_MAIN_CALL_RINGING_TIME, nowDateStr);
                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);

                    } else if (callState.getChannelName().contains(callState.getCallee())) { //被叫响铃

                        redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_RINGING_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                        redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_RINGING, Constants.TRUE);
                        redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_TARGET_CALL_RINGING_TIME, nowDateStr);
                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);

                    }
                    break;

                case CHANNEL_ANSWER:
                    logger.info("呼叫中间状态destinationNumber:{},ChannelName:{},sessionId:{},caller:{},callee:{}",callState.getDestinationNumber(),callState.getChannelName(),callState.getSessionId(),callState.getCaller(),callState.getCallee());
                    if (callState.getChannelName().contains(callState.getCaller())) {//主叫接通,正在接通被叫 ---当做主叫接通和被叫响铃时间
                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_MAIN_ANSWERED);
                        redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_ANSWERED, Constants.TRUE);
                        redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_ANSWERED_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                        redisSaveMap.put(RedisFields.RECEIVE_HISTORY_MAIN_CALL_ANSWERED_TIME, nowDateStr);


                    } else if (callState.getChannelName().contains(callState.getCallee())) { //呼叫建立，正在通话(被叫应答)

                        logger.info("freeswitch开始进行录音: sessionId:" + callState.getOut_id() + " 主叫:" + callState.getCaller() + ",被叫:" + callState.getCallee());
                        String result = startRecord(callState.getOut_id());

                        if (result.equals(GlobalStatic.FAIL)) {
                            logger.info("freeswitch录音异常: sessionId:" + callState.getOut_id() + " 主叫:" + callState.getCaller() + ",被叫:" + callState.getCallee());
                        }

                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_TARGET_ANSWERED);

                        redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_ANSWERED, Constants.TRUE);
                        redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_ANSWERED_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                        redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_TARGET_CALL_ANSWERED_TIME, nowDateStr);

                    }else{
                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);
                    }

                    break;

                case CHANNEL_HANGUP:   //呼叫结束（双呼） 返回的呼叫状态
                    //客户不接->客户无接听
                    //客户接，经纪还没接，客户就挂断->客户挂机
                    //客户接、经纪接->结束通话
                    try {
                        if (callHistoryMap.get(RedisFields.CALL_HISTORY_DISCONNECT_TIME) == null) { //由于会发多次，取第一次和账单那次就好，呼入账单状态回来就入库和推置业

                            //通话结束状态回来以后将该使用用户的繁忙状态改为否
                            if (callHistoryMap.get(RedisFields.CREATE_USER_ID) != null) {
                                redisTemplate.opsForHash().put(RedisKey.USER_BUSY, callHistoryMap.get(RedisFields.CREATE_USER_ID), Constants.FALSE);
                            }
                            redisSaveMap.put(RedisFields.CALL_HISTORY_DISCONNECT_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                            redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_DISCONNECT_TIME, nowDateStr);

                            if (!Constants.TRUE.equals(callHistoryMap.get(RedisFields.CALL_HISTORY_MAIN_CALL_ANSWERED))&&!Constants.TRUE.equals(callHistoryMap.get(RedisFields.CALL_HISTORY_TARGET_CALL_ANSWERED))) { //呼叫经纪失败，（各种原因）

                                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_MAIN_FAILED);
                                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_DESC, Constants.FJ_TELECOM_FAILED_REASON_MAIN_FAILED_4);

                                redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_FAILED, Constants.TRUE);
                                redisSaveMap.put(RedisFields.CALL_HISTORY_MAIN_CALL_FAILED_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                                redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_MAIN_CALL_FAILED_TIME, nowDateStr);

                            } else if (!Constants.TRUE.equals(callHistoryMap.get(RedisFields.CALL_HISTORY_TARGET_CALL_ANSWERED))) { //呼叫客户失败（各种原因）

                                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_TARGET_FAILED);
                                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_DESC, Constants.FJ_TELECOM_FAILED_REASON_MAIN_FAILED_5);

                                redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_FAILED, Constants.TRUE);
                                redisSaveMap.put(RedisFields.CALL_HISTORY_TARGET_CALL_FAILED_TIME, DateUtils.stringFromString(callState.getStatus_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                                redisSaveMap.put(RedisFields.RECEIVE_CALL_HISTORY_TARGET_CALL_FAILED_TIME, nowDateStr);

                            } else { //正常通话结束
                                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_TARGET_DISCONNECTED);

                                //这里生产录音url ，因为只有正常通话才有录音
                                try {
                                    Object recordFilePath = redisTemplate.opsForHash().get(RedisKey.CALL_HISTORY_RPIX + callState.getSessionId() + "_temp", "recordFilePath");

                                    if (StringUtil.isNotNull(recordFilePath)) { //不为空有文件，将Url 放入redis
                                        redisSaveMap.put(RedisFields.CALL_HISTORY_RECORD_FILE_URL,recordFilePath.toString());
                                        logger.info("freeswitchLog :  生成freeswitch录音文件url:" ,recordFilePath.toString());
                                        redisTemplate.delete(RedisKey.CALL_HISTORY_RPIX + callState.getSessionId() + "_temp");//取了以后删除key
                                    }
                                }catch (Exception e){
                                    logger.error(">>>生成录音文件url异常");
                                }

                            }

                        } else { //多余的状态不推送到客户端
                            msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);

                        }
                    } catch (Exception e) { //防止话单比结束状态早回来的情况
                        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_TARGET_DISCONNECTED);
                    }

                    break;
                case CUSTOM:
                    String subclass = event.getEventHeaders().get("Event-Subclass");
                    // sofia::register sofia::unregister alibaba_asr::onSentenceEnd dial::gateway_not_registered dial::lineBusy"
                    switch (subclass){
                        case EventSubClassName.DIAL_GATEWAY_NOT_REGISTER:
                            logger.info(">>fs网关未注册");
                            msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_GATEWAY_NOT_REGISTERED);
                            redisSaveMap.put(RedisFields.CALL_HISTORY_FAILED_REASON, "网关未注册");
                            break;
                        case EventSubClassName.DIAL_LINE_BUSY:
                            logger.info(">>fs线路忙");
                            msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_LINE_BUSY);
                            redisSaveMap.put(RedisFields.CALL_HISTORY_FAILED_REASON, "线路忙");
                            break;
                        default:
                            //多余状态不推送到客户端
                            msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);
                            break;
                    }
                    break;
                default:
                    //多余状态不推送到客户端
                    msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);
                    break;

            }

            if (!Constants.CALL_OUT.toString().equals(callHistoryMap.get(RedisFields.CALL_HISTORY_CALL_TYPE))) { //呼入状态不返回客户端
                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);
            }

            //如果中断，后续的数据不发送到客户端
            if (redisTemplate.opsForValue().get(RedisKey.INTERRUPT_FAIL + callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID)) != null) {

                redisSaveMap.put(RedisFields.CALL_HISTORY_REMARK, Constants.LOCAL_MSG_CALL_CANCEL);
                msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);
            }

        } else if (callState.getMsgType().equals(AliyunAkInfo.VOICEREPORT)) {//呼出话务单话务单回来之后才推送给持久化服务

            logger.info(">>>>>>生成话单：{}",callState.getSessionId());
             //清除map
            EventSocketInitBean.clearCallMapByKey(callState.getSessionId());
            //呼出话单处理
            if (Constants.CALL_OUT.toString().equals(callHistoryMap.get(RedisFields.CALL_HISTORY_CALL_TYPE))) {   //处理呼出话单，

                String statusCode = callState.getStatus_code();
                String statusMsg = callState.getStatus_msg();
                if (statusMsg != null) {
                    redisSaveMap.put(RedisFields.CALL_HISTORY_REMARK, statusMsg);
                }
                //手动取消外呼显示取消外呼
                logger.info("fscall------------------INTERRUPT：{}", callHistoryMap.get(RedisFields.INTERRUPT));

                if (callHistoryMap.get(RedisFields.INTERRUPT) != null
                        && Constants.INTERRUPT.toString().equals(callHistoryMap.get(RedisFields.INTERRUPT))) {
                    redisSaveMap.put(RedisFields.CALL_HISTORY_FAILED_REASON, Constants.LOCAL_MSG_CALL_CANCEL);

                } else if (!(CHANNEL_HANGUP_COMPLETE==EventName.fromName(statusCode))) {
                    redisSaveMap.put(RedisFields.CALL_HISTORY_FAILED_REASON, statusMsg);
                }

                if (StringTools.isNotempty(callState.getA_duration())) { //主叫时长

                    redisSaveMap.put(RedisFields.MAIN_CALL_LENGTH, callState.getA_duration());

                }

                if (StringTools.isNotempty(callState.getA_start_time())) { // 主叫开始时间可

                    redisSaveMap.put(RedisFields.MAIN_CALL_START_TIME, callState.getA_start_time());
                }

                if (StringTools.isNotempty(callState.getA_end_time())) { // 主叫结束时间

                    redisSaveMap.put(RedisFields.MAIN_CALL_END_TIME, callState.getA_end_time());
                }


                if (StringTools.isNotempty(callState.getDuration())) { //被叫通话时长可能没有这个时间
                    redisSaveMap.put(RedisFields.TARGET_CALL_LENGTH, callState.getDuration());
                    //通话时长,目前取被叫的通话时长
                    redisSaveMap.put(RedisFields.CALL_HISTORY_RECORD_TIME_LENTH, callState.getDuration());
                }else if (StringTools.isNotempty(callState.getA_duration())){ //没有主叫时长,说明主叫没接通,不设置通话时长
                    redisSaveMap.put(RedisFields.CALL_HISTORY_RECORD_TIME_LENTH, "0");
                }

                if (StringTools.isNotempty(callState.getStart_time())) { //被叫开始时间

                    redisSaveMap.put(RedisFields.TARGET_CALL_START_TIME, callState.getStart_time());
                }
                if (StringTools.isNotempty(callState.getEnd_time())) { //被叫结束时间可能没有这个时间

                    redisSaveMap.put(RedisFields.TARGET_CALL_END_TIME, callState.getEnd_time());
                }

            } else {   //呼入
                //这里的状态有点错误，特殊处理下

                if (StringTools.isNotempty(callState.getStart_time())) { //可能没有这个时间
                    redisSaveMap.put(RedisFields.TARGET_CALL_START_TIME, DateUtils.stringFromString(callState.getStart_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                }
                if (StringTools.isNotempty(callState.getEnd_time())) { //可能没有这个时间
                    redisSaveMap.put(RedisFields.TARGET_CALL_END_TIME, DateUtils.stringFromString(callState.getEnd_time(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                }

                if (StringTools.isNotempty(callState.getDuration())) { //可能没有这个时间
                    redisSaveMap.put(RedisFields.CALL_HISTORY_RECORD_TIME_LENTH, callState.getDuration());
                    redisSaveMap.put(RedisFields.TARGET_CALL_LENGTH, callState.getDuration());

                }
            }
            //话务单回来也不需要发送到客户端
            msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_INVALID);

        }

        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_TIME, nowDateStr);
        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_SESSION_ID, callState.getOut_id());
        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_DATA_ID, callHistoryMap.get(RedisFields.CALL_HISTORY_DATA_ID));
        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_PAGE_FROM, callHistoryMap.get(RedisFields.CALL_HISTORY_PAGE_FROM));
        msgMap.put(Constants.WEB_SOCKET_JSON_KEY_MACHINE_FROM, callHistoryMap.get(RedisFields.CALL_HISTORY_MACHINE_FROM));

        resultMap.put(Constants.CALL_STATE_WORK_HANDLER_MAP_KEY_MSG, msgMap);
        resultMap.put(Constants.CALL_STATE_WORK_HANDLER_MAP_KEY_REDIS, redisSaveMap);

        return resultMap;

    }

    /**
     * 将呼叫消息推送到ES和
     *
     * @param callHistoryMap
     */
    @Override
    protected void todoSaveCallRcord(Map<String, String> callHistoryMap) {
        try {
            String jsonStr = JSONObject.toJSONString(callHistoryMap);
            pushDataToEsTaskExecutor.execute(() -> {
                pushDataToEsBiz.pushCallHistoryToEs(callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID), jsonStr, RedisKey.CALL_HISTORY_RPIX + callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID),false);
            });

        } catch (Exception e) {
            try {
                redisTemplate.opsForSet().add(RedisKey.PUSH_TO_ES_FAILED_HISTORY, callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID));
            } catch (Exception e1) {
                logger.error("将推送ES 失败数据放入redis 失败！sessionId：{}", callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID), e1);
            }
            logger.error("====>推送Es 的线程池爆了", e);
        }
    }


    /**
     * 将呼叫消息推送到置业Oracle
     *
     * @param callHistoryMap
     */
    @Override
    protected void pushCallRcordToOracle(Map<String, String> callHistoryMap) {

        try {
            pushDataToOracleTaskExecutor.execute(() -> {
                pushDataToOracleBiz.pushData(callHistoryMap);
            });
        } catch (Exception e) {
            logger.error("====>推送置业Oracle失败", e);
            pushDataToOracleBiz.setReids("record",callHistoryMap.get(RedisFields.CALL_HISTORY_SESSION_ID));
        }

    }


    protected  void pushCallRcordToHbase(Map<String,String> callHistoryMap){
        //异步操作
        BeanUtils.getPushDataToHbaseBiz().pushDataToHbase(callHistoryMap);
    }
    /**
     * 推送到websocket
     *
     * @param callHistoryMap
     * @param resultMap
     * @throws Exception
     */
    @Override
    protected void pushStateToClient(Map<String, String> callHistoryMap, Map<String, Map<String, String>> resultMap) throws Exception {
        Map<String, String> msgMap = resultMap.get(Constants.CALL_STATE_WORK_HANDLER_MAP_KEY_MSG);
        String sessionId = callHistoryMap.get(Constants.WEB_SOCKET_JSON_KEY_SESSION_ID);

        //呼入暂时不推送数据到客户端
        if ("1".equals(callHistoryMap.get(RedisFields.CALL_HISTORY_CALL_TYPE))
                || Constants.WEB_SOCKET_MSG_TYPE_INCOME.equals(msgMap.get(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE))) {
            logger.debug("INCOME msg,dont send to client");
            return;
        }
        if (Constants.WEB_SOCKET_MSG_TYPE_INVALID.equals(msgMap.get(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE))) {
            logger.debug("INVALID msg, dont send to client");
            return;
        }

        String json = JSONObject.toJSONString(msgMap);

        logger.debug("FreeswitchStateWorkHandler pushStateToClient--->data:" + json);

        String rs = webSocketUtils.pushToClientBySessionId(sessionId, json);
        if (Constants.FAIL.equals(rs) || rs == null)
            logger.error("fscallCallStateWorkHandler pushStateToClient--->rs:{},sessionId:{}", rs, sessionId);
    }

    /**
     * 暂时不用
     *
     * @param callHistoryMap
     */
    @Override
    protected void pushRecordToBL(Map<String, String> callHistoryMap) {


    }


    /**
     * 录音操作
     *
     * @param channelUUid
     */
    public String startRecord(String channelUUid) {

        try {

            SendMsg msg = new SendMsg(channelUUid);
            msg.addCallCommand("execute");
            msg.addExecuteAppName("record_session");
            String filePath = "${strftime(%Y%m%d)}/${uuid}.wav";
            String fileUrl = DateUtils.formatDate(new Date(), "yyyyMMdd")+"/"+channelUUid+".wav";
            int ranNum = new Random().nextInt(2);
            String myrecordFilePath =recordFilePath;
            String myrecordFileUrl = recordFileUrl;
            if(ranNum==1){
                myrecordFilePath = recordFilePath.replace("50","51");
               // recordFilePath = recordFilePath.replace("50","51");
                myrecordFileUrl = recordFileUrl.substring(0,recordFileUrl.lastIndexOf("/"))+"51/";
              //  recordFileUrl = recordFileUrl.substring(0,recordFileUrl.lastIndexOf("/"))+"51/";
            }
            msg.addExecuteAppArg( myrecordFilePath+ filePath);
            hashOperations.put(RedisKey.CALL_HISTORY_RPIX + channelUUid + "_temp", "recordFilePath", serverUrl + myrecordFileUrl +fileUrl);
            // msg.addExecuteAppArg("$${base_dir}/recordings/${strftime(%Y%m%d)}/${uuid}.wav");
            //有效时间为一天
            redisTemplate.expire(RedisKey.CALL_HISTORY_RPIX + channelUUid + "_temp", RedisTimeOut.CACHE_ONE_DAY, TimeUnit.SECONDS);
            initBean.getClient().sendMessage(msg);

            return GlobalStatic.SUCCESS;

        } catch (Exception e) {

            e.printStackTrace();

            return GlobalStatic.FAIL;
        }

    }


    public static void main(String[] args) {
        String recordFileUrl = "https://aicall.ihk.cn:9443/fscall/freeswitchRecord/";
        String recordFileUrl51 = recordFileUrl.substring(0,recordFileUrl.lastIndexOf("/"))+"51/";

        System.out.println(recordFileUrl51);


    }

}
